﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;

namespace YmatouAPI.Test
{
    /// <summary>
    /// 
    /// </summary>
    public static class DeepClone
    {
        /// <summary>
        /// 深度复制对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object DeepCopy(this object obj)
        {
            Object targetDeepCopyObj;
            Type targetType = obj.GetType();
            //值类型
            if (targetType.IsValueType == true)
            {
                targetDeepCopyObj = obj;
            }
            //引用类型 
            else
            {
                targetDeepCopyObj = System.Activator.CreateInstance(targetType);   //创建引用对象 
                System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers();

                foreach (System.Reflection.MemberInfo member in memberCollection)
                {
                    if (member.MemberType == System.Reflection.MemberTypes.Field)
                    {
                        System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member;
                        Object fieldValue = field.GetValue(obj);
                        if (fieldValue is ICloneable)
                        {
                            field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone());
                        }
                        else
                        {
                            field.SetValue(targetDeepCopyObj, DeepCopy(fieldValue));
                        }
                    }
                    else if (member.MemberType == System.Reflection.MemberTypes.Property)
                    {
                        System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member;
                        System.Reflection.MethodInfo info = myProperty.GetSetMethod(false);
                        if (info != null)
                        {
                            object propertyValue = myProperty.GetValue(obj, null);
                            if (propertyValue is ICloneable)
                            {
                                myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null);
                            }
                            else
                            {
                                myProperty.SetValue(targetDeepCopyObj, DeepCopy(propertyValue), null);
                            }
                        }

                    }
                }
            }
            return targetDeepCopyObj;
        }
        /// <summary>
        /// 创建对象默认的实力数据
        /// </summary>
        /// <param name="objType"></param>
        /// <returns></returns>
        public static object CreateDefaultObj(this Type objType)
        {
            Object targetDeepCopyObj;
            //值类型
            if (objType.IsValueType)
            {
                if (objType.FullName == "System.DateTime")
                {
                    targetDeepCopyObj = DateTime.Now.ToString();
                }
                else
                {
                    targetDeepCopyObj = objType;
                }
            }
            //引用类型 
            else
            {
                targetDeepCopyObj = System.Activator.CreateInstance(objType);
                foreach (var property in objType.GetProperties())
                {
                    object propertyValue = property.GetValue(targetDeepCopyObj, null);
                    if (propertyValue == null)
                    {
                        if (!property.CanWrite) continue;

                        if (property.PropertyType.FullName == "System.String")
                        {
                            property.SetValue(targetDeepCopyObj, string.Empty);
                            continue;
                        }
                        if (property.PropertyType.FullName == "System.DateTime")
                        {
                            property.SetValue(targetDeepCopyObj, DateTime.Now.ToString());
                            continue;
                        }
                        if (property.PropertyType.FullName == "System.String[]")
                        {
                            property.SetValue(targetDeepCopyObj, new System.String[]{"test"});
                            continue;
                        }
                        if (property.PropertyType.Name == "IList`1")
                        {
                            //property.SetValue(targetDeepCopyObj, new System.String[] { "test" });
                            continue;
                        }
                        //父类
                        if (property.PropertyType.BaseType != null)
                        {
                            //null 可空类型， 对象
                            if (property.PropertyType.BaseType.FullName == "System.ValueType")
                            {
                                property.SetValue(targetDeepCopyObj, null);
                                continue;
                            }
                            //泛型
                            if (property.PropertyType.IsGenericType)
                            {
                                //泛型列表 list
                                if (property.PropertyType.Name == "List`1")
                                {
                                    Type d1 = typeof(List<>);
                                    var genericArguments = property.PropertyType.GetGenericArguments()[0];
                                    Type d2 = d1.MakeGenericType(genericArguments);
                                    var tempList = System.Activator.CreateInstance(d2);
                                    var isHit = false;
                                    //值类型泛型
                                    if (genericArguments.Name == "Int32")
                                    {
                                        d2.InvokeMember("Add",
                                            System.Reflection.BindingFlags.InvokeMethod,
                                            null,
                                            tempList,
                                           new object[] { 1 });
                                        //
                                        isHit = true;
                                    }
                                    //泛型String
                                    if (genericArguments.Name == "String")
                                    {
                                        d2.InvokeMember("Add",
                                                                                   System.Reflection.BindingFlags.InvokeMethod,
                                                                                   null,
                                                                                   tempList,
                                                                                  new object[] { "test" });
                                        //
                                        isHit = true;
                                    }
                                    //泛型对象
                                    if (!isHit)
                                    {
                                        d2.InvokeMember("Add",
                                                                                   System.Reflection.BindingFlags.InvokeMethod,
                                                                                   null,
                                                                                   tempList,
                                                                                  new object[] { CreateDefaultObj(genericArguments) });
                                        //
                                    }
                                    property.SetValue(targetDeepCopyObj, tempList);
                                    continue;
                                }

                            }
                        }

                        //
                        property.SetValue(targetDeepCopyObj, CreateDefaultObj(property.PropertyType));
                    }
                }
            }
            return targetDeepCopyObj;
        }

        /// <summary>
        /// 泛型类型转换
        /// </summary>
        /// <typeparam name="T">要转换的基础类型</typeparam>
        /// <param name="val">要转换的值</param>
        /// <returns></returns>
        /// <remark>
        /// </remark>
        public static T ConvertType<T>(object val)
        {
            if (val == null) return default(T);//返回类型的默认值
            Type tp = typeof(T);
            //泛型Nullable判断，取其中的类型
            if (tp.IsGenericType)
            {
                tp = tp.GetGenericArguments()[0];
            }
            //string直接返回转换
            if (tp.Name.ToLower() == "string")
            {
                return (T)val;
            }
            //反射获取TryParse方法
            var TryParse = tp.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder,
                                            new Type[] { typeof(string), tp.MakeByRefType() },
                                            new ParameterModifier[] { new ParameterModifier(2) });
            var parameters = new object[] { val, Activator.CreateInstance(tp) };
            bool success = (bool)TryParse.Invoke(null, parameters);
            //成功返回转换后的值，否则返回类型的默认值
            if (success)
            {
                return (T)parameters[1];
            }
            return default(T);
        }
    }
}